package com.siao.component.scroller
{
	import com.greensock.TweenMax;
	import com.greensock.easing.Strong;
	import com.siao.component.IDataItem;
	import com.siao.component.ISelectItem;
	import com.siao.component.ISelector;
	import com.siao.component.Orientation;
	import com.siao.core.FlashPlayer;
	import com.siao.data.ArrayList;
	import com.siao.display.Align;
	import com.siao.display.LayoutElement;
	import com.siao.display.Margin;
	import com.siao.events.DataChangeEvent;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.external.ExternalInterface;
	import flash.geom.Point;
	import flash.utils.clearInterval;
	import flash.utils.getTimer;
	import flash.utils.setInterval;
	
	[Event(name="select", type="flash.events.Event")]
	
	/**
	 * 滚动列表
	 * @author SiaoLeon
	 */
	public class ScrollList extends LayoutElement implements ISelector
	{
		// -------------------------------------------------------------------------------------------------------- 静态常量
		
		// -------------------------------------------------------------------------------------------------------- 静态变量
		
		// -------------------------------------------------------------------------------------------------------- 静态方法
		
		// -------------------------------------------------------------------------------------------------------- 静态函数
		
		// -------------------------------------------------------------------------------------------------------- 属性
		
		private var _selected:*;
		
		public function get selected():*
		{
			return this._selected;
		}
		
		public function set selected(value:*):void
		{
			this._selected = value;
			
			for each (var item:ISelectItem in this.items)
			{
				if (item == null || !(item is IDataItem))
				{
					continue;
				}
				
				item.selected = (this.selected == (item as IDataItem).data || ((this.selected is ArrayList) && (this.selected as ArrayList).contains((item as IDataItem).data)));
			}
			
			this.dispatchEvent(new Event(Event.SELECT));
		}
		
		private var _width:Number;
		
		override public function set width(value:Number):void
		{
			this._width = super.width = value;;
		}
		
		private var _height:Number;
		
		override public function set height(value:Number):void
		{
			this._height = super.height = value;;
		}
		
		/**
		 * 最小缓动时长（单位：秒）
		 * @default 0.8
		 */
		public var minEaseTime:Number = 0.8;
		
		/**
		 * 最大缓动时长（单位：秒）
		 * @default 2.5
		 */
		public var maxEaseTime:Number = 2.5;
		
		/**
		 * 拖动内容时检测位移间隔时间（单位：毫秒）
		 * @default  100
		 */
		public var dragRate:Number = 100;
		
		/**
		 * 拖拽松开时缓动系数
		 * @default 300
		 */
		public var dragEase:Number = 300;
		
		/**
		 * 是否允许多选，设置此选项为true时将允许用户按住Ctrl键进行多选
		 * @default false
		 */
		public var multiSelected:Boolean;
		
		/**
		 * 左侧过量拖拽数值
		 * @default 0
		 */
		public var overDragLeft:Number = 0;
		
		/**
		 * 右侧过量拖拽数值
		 * @default 0
		 */
		public var overDragRight:Number = 0;
		
		/**
		 * 顶部过量拖拽数值
		 * @default 0
		 */
		public var overDragTop:Number = 0;
		
		/**
		 * 底部过量拖拽数值
		 * @default 0
		 */
		public var overDragBottom:Number = 0;
		
		/**
		 * 设置过量拖拽数值
		 * @param value
		 */
		public function set overDrag(value:Number):void
		{
			this.overDragLeft = this.overDragRight = this.overDragTop = this.overDragBottom = value;
		}
		
		private var _scrollEasing:Boolean;
		
		/**
		 * 是否开启缓动模式
		 * @return
		 */
		public function get scrollEasing():Boolean
		{
			return this._scrollEasing;
		}
		
		public function set scrollEasing(value:Boolean):void
		{
			this._scrollEasing = value;
		}
		
		private var _scrollDrag:Boolean;
		
		/**
		 * 是否开启内容拖拽
		 * @return
		 */
		public function get scrollDrag():Boolean
		{
			return this._scrollDrag;
		}
		
		public function set scrollDrag(value:Boolean):void
		{
			this._scrollDrag = value;
			
			this.registerEventListeners();
		}
		
		private var _scrollWheel:Boolean;
		
		/**
		 * 是否开启鼠标滚轮垂直滚动
		 * @return
		 */
		public function get scrollWheel():Boolean
		{
			return this._scrollWheel;
		}
		
		public function set scrollWheel(value:Boolean):void
		{
			this._scrollWheel = value;
			
			this.registerEventListeners();
		}
		
		private var _required:Boolean;
		
		/**
		 * 是否必选模式，必选模式将默认选择数据列表中的首数据
		 * @return
		 */
		public function get required():Boolean
		{
			return this._required;
		}
		
		public function set required(value:Boolean):void
		{
			this._required = value;
			
			if (this.cancelMode && value)
			{
				this.cancelMode = false;
			}
			
			if (this.required && this.selected == null && this.data != null && this.data.length > 0)
			{
				this.selected = this.data.element(0);
			}
			
			this.registerEventListeners();
		}
		
		private var _cancelMode:Boolean;
		
		/**
		 * 是否支持可取消选择，可取消时点击舞台其他区域将取消选择
		 * @return
		 */
		public function get cancelMode():Boolean
		{
			return this._cancelMode;
		}
		
		public function set cancelMode(value:Boolean):void
		{
			this._cancelMode = value;
			
			if (this.required && value)
			{
				this.required = false;
			}
			
			this.registerEventListeners();
		}
		
		private var _wrap:Boolean
		
		/**
		 * 是否自动换行
		 * @return
		 */
		public function get wrap():Boolean
		{
			return this._wrap;
		}
		
		public function set wrap(value:Boolean):void
		{
			this._wrap = value;
			
			this.init();
		}
		
		private var _scrollSize:Number;
		
		/**
		 * 行/列尺寸，该数值将影响向前、向后滚动的间隔尺寸
		 * @return
		 */
		public function get scrollSize():Number
		{
			return this._scrollSize;
		}
		
		public function set scrollSize(value:Number):void
		{
			this._scrollSize = value;
			
			this.initScrollBar();
		}
		
		private var _rowSpacing:Number = 0;
		
		/**
		 * 行间距
		 * @return
		 */
		public function get rowSpacing():Number
		{
			return this._rowSpacing;
		}
		
		public function set rowSpacing(value:Number):void
		{
			this._rowSpacing = value;
			
			this.init();
		}
		
		private var _colSpacing:Number = 0;
		
		/**
		 * 列间距
		 * @return
		 */
		public function get colSpacing():Number
		{
			return this._colSpacing;
		}
		
		public function set colSpacing(value:Number):void
		{
			this._colSpacing = value;
			
			this.init();
		}
		
		private var _contentAlignH:uint;
		
		/**
		 * 显示内容水平对齐方式
		 * @return
		 */
		public function get contentAlignH():uint
		{
			return this._contentAlignH;
		}
		
		public function set contentAlignH(value:uint):void
		{
			this._contentAlignH = value;
			
			this.init();
		}
		
		private var _contentAlignV:uint;
		
		/**
		 * 显示内容垂直对齐方式
		 * @return
		 */
		public function get contentAlignV():uint
		{
			return this._contentAlignV;
		}
		
		public function set contentAlignV(value:uint):void
		{
			this._contentAlignV = value;
			
			this.init();
		}
		
		private var _orientation:uint;
		
		/**
		 * 排列方式
		 * @return
		 */
		public function get orientation():uint
		{
			return this._orientation;
		}
		
		public function set orientation(value:uint):void
		{
			this._orientation = (value > Orientation.BOTTOM_TOP) ? value & 1 : value;
			
			this.init();
		}
		
		private var _wrapOrientation:uint;
		
		/**
		 * 换行方式
		 * @return
		 */
		public function get wrapOrientation():uint
		{
			return this._wrapOrientation;
		}
		
		public function set wrapOrientation(value:uint):void
		{
			this._wrapOrientation = (value > Orientation.BOTTOM_TOP) ? value & 1 : value;
			
			this.init();
		}
		
		private var _maskMargin:Margin = new Margin();
		
		/**
		 * 设置遮罩外边距
		 * @param value
		 */
		public function set maskMargin(value:Number):void
		{
			this._maskMargin.left = this._maskMargin.right = this._maskMargin.top = this._maskMargin.right = value;
			
			this.init();
		}
		
		/**
		 * 遮罩左侧外边距
		 * @return
		 */
		public function get maskMarginLeft():Number
		{
			return this._maskMargin.left;
		}
		
		public function set maskMarginLeft(value:Number):void
		{
			this._maskMargin.left = value;
			
			this.init();
		}
		
		/**
		 * 遮罩右侧外边距
		 * @return
		 */
		public function get maskMarginRight():Number
		{
			return this._maskMargin.right;
		}
		
		public function set maskMarginRight(value:Number):void
		{
			this._maskMargin.right = value;
			
			this.init();
		}
		
		/**
		 * 遮罩顶部外边距
		 * @return
		 */
		public function get maskMarginTop():Number
		{
			return this._maskMargin.top;
		}
		
		public function set maskMarginTop(value:Number):void
		{
			this._maskMargin.top = value;
			
			this.init();
		}
		
		/**
		 * 遮罩底部外边距
		 * @return
		 */
		public function get maskMarginBottom():Number
		{
			return this._maskMargin.bottom;
		}
		
		public function set maskMarginBottom(value:Number):void
		{
			this._maskMargin.bottom = value;
			
			this.init();
		}
		
		private var _vScrollBar:ScrollBar;
		
		/**
		 * 垂直滚动条
		 * @return
		 */
		public function get vScrollBar():ScrollBar
		{
			return (this._vScrollBar == null) ? new ScrollBar() : this._vScrollBar;
		}
		
		public function set vScrollBar(value:ScrollBar):void
		{
			if (this.contains(this.vScrollBar))
			{
				this.removeChild(this.vScrollBar);
			}
			
			this.vScrollBar.removeEventListener(Event.CHANGE, onScroll);
			
			this._vScrollBar = value;
			this.vScrollBar.alignH = Align.RIGHT;
			this.addChild(this.vScrollBar);
			
			this.init();
		}
		
		private var _hScrollBar:ScrollBar;
		
		/**
		 * 水平滚动条
		 * @return
		 */
		public function get hScrollBar():ScrollBar
		{
			return (this._hScrollBar == null) ? new ScrollBar() : this._hScrollBar;
		}
		
		public function set hScrollBar(value:ScrollBar):void
		{
			if (this.contains(this.hScrollBar))
			{
				this.removeChild(this.hScrollBar);
			}
			
			this.hScrollBar.removeEventListener(Event.CHANGE, onScroll);
			
			this._hScrollBar = value;
			this.hScrollBar.alignV = Align.BOTTOM;
			this.addChild(this.hScrollBar);
			
			this.init();
		}
		
		private var _itemClass:Class;
		
		/**
		 * 项目类型，该类型必须继承IDataItem接口，并是DisplayObject的子类
		 * @return
		 */
		public function get itemClass():Class
		{
			return this._itemClass;
		}
		
		public function set itemClass(value:Class):void
		{
			this._itemClass = value;
			
			if (this.itemClass != null && this.data != null)
			{
				this.bind(this.itemClass, this.data);
			}
		}
		
		private var _data:ArrayList;
		
		/**
		 * 列表数据
		 * @return
		 */
		public function get data():ArrayList
		{
			return this._data;
		}
		
		public function set data(value:ArrayList):void
		{
			this._data = value;
			
			if (this.itemClass != null && this.data != null)
			{
				this.bind(this.itemClass, this.data);
			}
		}
		
		private var _row:uint;
		
		/**
		 * 行数
		 * @return
		 */
		public function get row():uint
		{
			return this._row;
		}
		
		private var _col:uint;
		
		/**
		 * 列数
		 * @return
		 */
		public function get col():uint
		{
			return this._col;
		}
		
		private var _itemWidth:Number;
		
		/**
		 * 项目宽度
		 * @return
		 */
		public function get itemWidth():Number
		{
			return this._itemWidth;
		}
		
		private var _itemHeight:Number;
		
		/**
		 * 项目高度
		 * @return
		 */
		public function get itemHeight():Number
		{
			return this._itemHeight;
		}
		
		private var _itemMaxWidth:Number;
		
		/**
		 * 项目最大宽度（仅当项目为LayoutElement时可用）
		 * @return
		 */
		public function get itemMaxWidth():Number
		{
			return this._itemMaxWidth;
		}
		
		private var _itemMaxHeight:Number;
		
		/**
		 * 项目最大高度（仅当项目为LayoutElement时可用）
		 * @return
		 */
		public function get itemMaxHeight():Number
		{
			return this._itemMaxHeight;
		}
		
		private var _contentWidth:Number;
		
		/**
		 * 内容宽度
		 * @return
		 */
		public function get contentWidth():Number
		{
			return this._contentWidth;
		}
		
		private var _contentHeight:Number;
		
		/**
		 * 内容高度
		 * @return
		 */
		public function get contentHeight():Number
		{
			return this._contentHeight;
		}
		
		// -------------------------------------------------------------------------------------------------------- 变量
		
		private var maskLayer:Sprite;
		
		private var container:LayoutElement;
		
		private var containerLocalX:Number;
		
		private var containerLocalY:Number;
		
		private var containerStartX:Number;
		
		private var containerStartY:Number;
		
		private var containerMouseInterval:uint;
		
		private var containerMouseTime:Number;
		
		private var tweenX:TweenMax;
		
		private var tweenY:TweenMax;
		
		private var items:Vector.<ScrollListItem> = new Vector.<ScrollListItem>();
		
		private var itemStartIndex:uint = 0;
		
		// -------------------------------------------------------------------------------------------------------- 构造
		
		/**
		 * 构造函数
		 */
		public function ScrollList(orientation:uint=Orientation.TOP_BOTTOM, wrapOrientation:uint=Orientation.LEFT_RIGHT, vScrollBar:ScrollBar=null, hScrollBar:ScrollBar=null)
		{
			super();
			
			this._orientation = (orientation > Orientation.RIGHT_LEFT) ? orientation & 1 : orientation;
			this._wrapOrientation = (wrapOrientation > Orientation.RIGHT_LEFT) ? wrapOrientation & 1 : wrapOrientation;
			this._vScrollBar = vScrollBar;
			this._hScrollBar = hScrollBar;
			this.vScrollBar.alignH = Align.RIGHT;
			this.hScrollBar.alignV = Align.BOTTOM;
			this.addChild(this.vScrollBar);
			this.addChild(this.hScrollBar);
			
			this.maskLayer = new Sprite();
			this.maskLayer.mouseEnabled = this.maskLayer.mouseChildren = false;
			this.maskLayer.graphics.beginFill(0X000000);
			this.maskLayer.graphics.drawRect(0, 0, 1, 1);
			this.maskLayer.graphics.endFill();
			this.addChild(this.maskLayer);
			
			this.container = new LayoutElement();
			this.container.draw(0XFF0000, 0);
			this.container.mask = this.maskLayer;
			this.addChild(this.container);
		}
		
		// -------------------------------------------------------------------------------------------------------- 方法
		
		override public function clear():void
		{
			for (var i:int = this.numChildren - 1; i >= 0; i--)
			{
				var child:DisplayObject = this.getChildAt(i);
				
				if (child == this.container || child == this.maskLayer || child == this.vScrollBar || child == this.hScrollBar)
				{
					continue;
				}
				
				this.removeChild(child);
			}
			
			while (this.container.numChildren > 0)
			{
				this.container.removeChildAt(0);
			}
			
			if (this.data != null)
			{
				this.data.removeEventListener(DataChangeEvent.CHANGE, onDataChange);
			}
			
			this.items.splice(0, this.items.length);
			this._itemClass = null;
			this._data = null;
			this._row = this._col = 0;
			this._itemWidth = this._itemHeight = this._itemMaxWidth = this._itemMaxHeight = Number.NaN;
		}
		
		override public function resize():void
		{
			if (this.stage == null || !this.visible)
			{
				return;
			}
			
			super.resize();
			
			this.resizeMask();
			this.measure();
			
			var range:Margin = this.dragRange();
			
			if (this.container.x < range.left)
			{
				this.container.x = range.left;
			}
			
			if (this.container.x > range.right)
			{
				this.container.x = range.right;
			}
			
			if (this.container.y < range.top)
			{
				this.container.y = range.top;
			}
			
			if (this.container.y > range.bottom)
			{
				this.container.y = range.bottom;
			}
			
			var showWidth:Number = this.width - this.paddingLeft - this.paddingRight - this._maskMargin.left - this._maskMargin.right;
			var showHeight:Number = this.height - this.paddingTop - this.paddingBottom - this._maskMargin.top - this._maskMargin.bottom;
			
			this.hScrollBar.visible = (this.height - this.paddingTop - this.paddingBottom >= this.hScrollBar.height && this.container.width > showWidth);
			this.vScrollBar.visible = (this.width - this.paddingLeft - this.paddingRight >= this.vScrollBar.width && this.container.height > showHeight);
			
			this.hScrollBar.visible = (this.vScrollBar.visible) ? this.container.width > showWidth - this.vScrollBar.width : this.hScrollBar.visible;
			this.vScrollBar.visible = (this.hScrollBar.visible) ? this.container.height > showHeight - this.hScrollBar.height : this.vScrollBar.visible;
			
			this.resizeMask();
			this.measure();
			this.initItems();
			this.positionItems();
			this.initScrollBar();
		}
		
		/**
		 * 移动内容显示位置，坐标以内容原点计算（显示区域相对于内容左上角的坐标位置）。如开启缓动则缓动位移至该位置。
		 * @param x
		 * @param y
		 */
		public function moveTo(x:Number, y:Number):void
		{
			x = this.maskMarginLeft - x;
			y = this.maskMarginTop - y;
			
			//检测单位模式定位
			x = (this.hScrollBar.unitDragMode) ? Math.round(x / this.hScrollBar.unit) * this.hScrollBar.unit : x;
			y = (this.vScrollBar.unitDragMode) ? Math.round(y / this.vScrollBar.unit) * this.vScrollBar.unit : y;
			
			//如果与当前位置一致则返回
			if (this.container.x == x && this.container.y == y)
			{
				return;
			}
			
			//更新滚动条位置
			if (!this.scrollEasing)
			{
				this.hScrollBar.current = this.maskMarginLeft - this.container.x;
				this.vScrollBar.current = this.maskMarginTop - this.container.y;
			}
			
			//移除所有缓动效果
			TweenMax.killTweensOf(this.container);
			
			if (this.scrollEasing)
			{
				//缓动
				var range:Margin = this.dragRange();
				//检测目标位置是否超出移动范围
				var targetX:Number = (x > range.right) ? (range.right + Math.min(this.overDragLeft, (x - range.right) / 2)) : (x < range.left) ? (range.left - Math.min(this.overDragRight, (range.left - x) / 2)) : x;
				var targetY:Number = (y > range.bottom) ? (range.bottom + Math.min(this.overDragTop, (y - range.bottom) / 2)) : (y < range.top) ? (range.top - Math.min(this.overDragBottom, (range.top - y) / 2)) : y;
				
				x = (x > range.right) ? Math.min(x, targetX + targetX - range.right) : (x < range.left) ? Math.max(x, targetX + targetX - range.left) : x;
				y = (y > range.bottom) ? Math.min(y, targetY + targetY - range.bottom) : (y < range.top) ? Math.max(y, targetY + targetY - range.top) : y;
				
				//设置缓动时间
				var time:Number = Math.max(Math.abs(this.container.x - x) / this.maskLayer.width, Math.abs(this.container.y - y) / this.maskLayer.height);
				
				this.tweenX = TweenMax.to(this.container, Math.min(this.maxEaseTime, Math.max(this.minEaseTime, time)), {x: x, ease: Strong.easeOut, onUpdate: updatePositionH, onUpdateParams: [targetX]});
				this.tweenY = TweenMax.to(this.container, Math.min(this.maxEaseTime, Math.max(this.minEaseTime, time)), {y: y, ease: Strong.easeOut, onUpdate: updatePositionV, onUpdateParams: [targetY]});
				
			}
			else
			{
				//定位
				this.container.x = x;
				this.container.y = y;
				
				this.positionItems();
			}
		}
		
		/**
		 * 拖拽内容显示位置，坐标以内容原点计算（显示区域相对于内容左上角的坐标位置）。该方法将直接设置内容坐标，不参与缓动效果。
		 * @param x
		 * @param y
		 */
		public function dragTo(x:Number, y:Number):void
		{
			x = this.maskMarginLeft - x;
			y = this.maskMarginTop - y;
			
			//检测单位模式定位
			x = (this.hScrollBar.unitDragMode) ? Math.round(x / this.hScrollBar.unit) * this.hScrollBar.unit : x;
			y = (this.vScrollBar.unitDragMode) ? Math.round(y / this.vScrollBar.unit) * this.vScrollBar.unit : y;
			
			var range:Margin = this.dragRange();
			
			//如果超量拖拽，仿IPHONE半数计算
			x = (x <= range.right) ? x : Math.min(range.right + this.overDragLeft, range.right + (this.mouseX - this.containerLocalX - this.paddingLeft - range.right) / 2);
			x = (x >= range.left) ? x : Math.max(range.left - this.overDragRight, range.left + (this.mouseX - this.containerLocalX - this.paddingLeft - range.left) / 2);
			
			//如果超量拖拽，仿IPHONE半数计算
			y = (y <= range.bottom) ? y : Math.min(range.bottom + this.overDragTop, range.bottom + (this.mouseY - this.containerLocalY - this.paddingTop - range.bottom) / 2);
			y = (y >= range.top) ? y : Math.max(range.top - this.overDragBottom, range.top + (this.mouseY - this.containerLocalY - this.paddingTop - range.top) / 2);
			
			//鼠标拖拽定位
			this.container.x = x;
			this.container.y = y;
			
			this.positionItems();
			
			//更新滚动条位置
			this.hScrollBar.current = this.maskMarginLeft - this.container.x;
			this.vScrollBar.current = this.maskMarginTop - this.container.y;
		}
		
		/**
		 * 拖拽范围
		 * @return
		 */
		public function dragRange():Margin
		{
			var minX:Number;
			var maxX:Number;
			
			switch (this.contentAlignH)
			{
				case Align.LEFT:
					minX = (this.container.width > this.maskLayer.width) ? this.maskMarginLeft + this.maskLayer.width - this.container.width : this.maskMarginLeft;
					maxX = this.maskMarginLeft;
					break;
				case Align.RIGHT:
					minX = this.maskMarginLeft + this.maskLayer.width - this.container.width;
					maxX = (this.container.width > this.maskLayer.width) ? this.maskMarginLeft : this.maskMarginLeft + this.maskLayer.width - this.container.width;
					break;
				default:
					minX = (this.container.width > this.maskLayer.width) ? this.maskMarginLeft + this.maskLayer.width - this.container.width : this.maskMarginLeft + (this.maskLayer.width - this.container.width) / 2;
					maxX = (this.container.width > this.maskLayer.width) ? this.maskMarginLeft : this.maskMarginLeft + (this.maskLayer.width - this.container.width) / 2;
					break;
			}
			
			var minY:Number;
			var maxY:Number;
			
			switch (this.contentAlignV)
			{
				case Align.TOP:
					minY = (this.container.height > this.maskLayer.height) ? this.maskMarginTop + this.maskLayer.height - this.container.height : this.maskMarginTop;
					maxY = this.maskMarginTop;
					break;
				case Align.BOTTOM:
					minY = this.maskMarginTop + this.maskLayer.height - this.container.height;
					maxY = (this.container.height > this.maskLayer.height) ? this.maskMarginTop : this.maskMarginTop + this.maskLayer.height - this.container.height;
					break;
				default:
					minY = (this.container.height > this.maskLayer.height) ? this.maskMarginTop + this.maskLayer.height - this.container.height : this.maskMarginTop + (this.maskLayer.height - this.container.height) / 2;
					maxY = (this.container.height > this.maskLayer.height) ? this.maskMarginTop : this.maskMarginTop + (this.maskLayer.height - this.container.height) / 2;
					break;
			}
			
			return new Margin(minX, minY, maxX, maxY);
		}
		
		/**
		 * 绑定数据
		 * @param itemClass 项目类型，该类型必须继承IDataItem接口，并是DisplayObject的子类
		 * @param data 列表数据
		 */
		public function bind(itemClass:Class, data:ArrayList):void
		{
			//移除所有缓动效果
			TweenMax.killTweensOf(this.container);
			
			this._itemClass = itemClass;
			this._data = data;
			this._data.addEventListener(DataChangeEvent.CHANGE, onDataChange, false, 0, true);
			
			if (this.data == null || this.itemClass == null)
			{
				return;
			}
			
			var item:IDataItem = new itemClass();
			this._itemWidth = (item as DisplayObject).width;
			this._itemHeight = (item as DisplayObject).height;
			
			if (item is LayoutElement)
			{
				this._itemMaxWidth = (item as LayoutElement).maxWidth;
				this._itemMaxHeight = (item as LayoutElement).maxHeight;
			}
			
			this.initScrollBar();
			this.initItems();
			this.onDataChange();
			
			if (this.required && this.selected == null)
			{
				this.selected = this.data.element(0);
			}
		}
		
		/**
		 * 更新水平位置
		 */
		private function updatePositionH(targetX:Number):void
		{
			this.hScrollBar.current = this.maskMarginLeft - this.container.x;
			
			var range:Margin = this.dragRange();
			
			//左侧超出限定范围时做反响运动
			if (this.container.x >= range.right && this.container.x >= targetX)
			{
				this.tweenX.updateTo({x: range.right, ease: Strong.easeOut, onUpdate: updatePositionH, onUpdateParams: [targetX]});
			}
			
			//右侧超出限定范围时做反响运动
			if (this.container.x <= range.left && this.container.x <= targetX)
			{
				this.tweenX.updateTo({x: range.left, ease: Strong.easeOut, onUpdate: updatePositionH, onUpdateParams: [targetX]});
			}
			
			this.positionItems();
		}
		
		/**
		 * 更新垂直位置
		 */
		private function updatePositionV(targetY:Number):void
		{
			this.vScrollBar.current = this.maskMarginTop - this.container.y;
			
			var range:Margin = this.dragRange();
			
			//顶部超出限定范围时做反响运动
			if (this.container.y > range.bottom && this.container.y > targetY)
			{
				this.tweenY.updateTo({y: range.bottom, ease: Strong.easeOut, onUpdate: updatePositionH, onUpdateParams: [targetY]});
			}
			
			//底部超出限定范围时做反响运动
			if (this.container.y < range.top && this.container.y < targetY)
			{
				this.tweenY.updateTo({y: range.top, ease: Strong.easeOut, onUpdate: updatePositionH, onUpdateParams: [targetY]});
			}
			
			this.positionItems();
		}
		
		// -------------------------------------------------------------------------------------------------------- 函数
		
		override protected final function init():void
		{
			if (this.stage == null || !this.visible)
			{
				return;
			}
			
			super.init();
			
			this.positionMask();
			
			this.positionContainer();
			this.positionItems();
			
			this.registerEventListeners();
		}
		
		override protected final function exit():void
		{
			super.exit();
			
			if (this.stage != null)
			{
				this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onDragMouseMove);
				this.stage.removeEventListener(MouseEvent.MOUSE_UP, onContentMouseUp);
				this.stage.removeEventListener(Event.MOUSE_LEAVE, onContentMouseUp);
			}
			
			if (ExternalInterface.available)
			{
				FlashPlayer.RemoveMouseWheelHandler(this.onMouseWheel);
			}
			
			this.removeEventListeners();
		}
		
		/**
		 * 初始化项目
		 */
		private function initItems():void
		{
			if (this.data == null || this.itemClass == null)
			{
				return;
			}
			
			//计算可显示的行数
			var showRow:uint =  Math.min(this.row, Math.ceil((this.maskLayer.height + this.rowSpacing) / (this.itemHeight + this.rowSpacing)) + 1);
			
			if (this.itemHeight == 0)
			{
				showRow = (this.wrap || this.orientation == Orientation.VERTICAL || this.orientation == Orientation.TOP_BOTTOM || this.orientation == Orientation.BOTTOM_TOP) ? this.row : 1;
			}
			
			if (this.maskLayer.height <= this.rowSpacing)
			{
				showRow = (this.maskLayer.height == 0) ? 0 : 1;
			}
			
			//计算可显示的列数
			var showCol:uint = Math.min(this.col, Math.ceil((this.maskLayer.width + this.colSpacing) / (this.itemWidth + this.colSpacing)) + 1);
			
			if (this.itemWidth == 0)
			{
				showCol = (this.wrap || this.orientation == Orientation.HORIZONTAL || this.orientation == Orientation.LEFT_RIGHT || this.orientation == Orientation.RIGHT_LEFT) ? this.col : 1;
			}
			
			if (this.maskLayer.width <= this.colSpacing)
			{
				showCol = (this.maskLayer.width == 0) ? 0 : 1;
			}
			
			//计算可显示的项目个数
			var showItemCount:uint = Math.min(this.data.length, showRow * showCol);
			
			for (var i:int = this.items.length - 1; i >= 0; i--)
			{
				var item:ScrollListItem = this.items[i];
				
				if (!(item.content is this.itemClass) || showItemCount <= i)
				{
					item.content.removeEventListener(MouseEvent.CLICK, onClick);
					this.container.removeChild(item.content);
					this.items.splice(i, 1);
				}
			}
			
			while (this.items.length < showItemCount)
			{
				var newItem:ScrollListItem =  new ScrollListItem(this.itemClass)
				newItem.content.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
				this.container.addChild(newItem.content);
				this.items.push(newItem);
			}
		}
		
		/**
		 * 定位项目
		 */
		private function positionItems():void
		{
			var overWidth:Number = this.maskMarginLeft - this.container.x;
			var overHeight:Number = this.maskMarginTop - this.container.y;
			
			var overRow:uint = (this.itemHeight == 0) ? 0 : Math.max(0, Math.floor((overHeight + this.rowSpacing) / (this.itemHeight + this.rowSpacing)));
			var overCol:uint = (this.itemWidth == 0) ? 0 : Math.max(0, Math.floor((overWidth + this.colSpacing) / (this.itemWidth + this.colSpacing)));
			
			var startIndex:uint = 0;
			
			switch (this.orientation)
			{
				case Orientation.HORIZONTAL:
				case Orientation.LEFT_RIGHT:
				case Orientation.RIGHT_LEFT:
					startIndex = overRow * this.col + overCol;
					break;
				
				case Orientation.VERTICAL:
				case Orientation.TOP_BOTTOM:
				case Orientation.BOTTOM_TOP:
					startIndex = overCol * this.row + overRow;
					break;
			}
			
			if (this.items.length > 0)
			{
				//根据起始位置重排项目
				for (var i:int = 0; i < Math.abs(startIndex - this.itemStartIndex); i++)
				{
					if (startIndex - this.itemStartIndex < 0)
					{
						this.items.unshift(this.items.pop());
					}
					
					if (startIndex - this.itemStartIndex > 0)
					{
						this.items.push(this.items.shift());
					}
				}
			}
			
			//计算每个项目的尺寸、位置
			for each (var item:ScrollListItem in this.items)
			{
				//计算项目尺寸
				if (this.itemWidth == 0)
				{
					item.content.width = Math.max(0, (this.maskLayer.width + this.colSpacing) / this.col - this.colSpacing);
				}
				
				if (this.itemHeight == 0)
				{
					item.content.height = Math.max(0, (this.maskLayer.height + this.rowSpacing) / this.row - this.rowSpacing);
				}
				
				//获取项目所在行、列
				var itemIndex:uint = startIndex + this.items.indexOf(item);
				var itemRow:uint = 0;
				var itemCol:uint = 0;
				
				if (item.index == itemIndex && item.row == itemRow && item.col == itemCol)
				{
					continue;
				}
				
				switch (this.orientation)
				{
					case Orientation.HORIZONTAL:
					case Orientation.LEFT_RIGHT:
						itemCol = (itemIndex + 1) % this.col;
						itemCol = (itemCol == 0) ? this.col : itemCol;
						itemRow = (this.wrapOrientation == Orientation.BOTTOM_TOP) ? this.row - Math.floor(itemIndex / this.col) : Math.ceil((itemIndex + 1) / this.col);
						break;
					case Orientation.RIGHT_LEFT:
						itemCol = this.col - itemIndex % this.col;
						itemRow = (this.wrapOrientation == Orientation.BOTTOM_TOP) ? this.row - Math.floor(itemIndex / this.col) : Math.ceil((itemIndex + 1) / this.col);
						break;
					
					case Orientation.VERTICAL:
					case Orientation.TOP_BOTTOM:
						itemRow = (itemIndex + 1) % this.row;
						itemRow = (itemRow == 0) ? this.row : itemRow;
						itemCol = (this.wrapOrientation == Orientation.RIGHT_LEFT) ? this.col - Math.floor(itemIndex / this.row) : Math.ceil((itemIndex + 1) / this.row);
						break;
					case Orientation.BOTTOM_TOP:
						itemRow = this.row - itemIndex % this.row;
						itemCol = (this.wrapOrientation == Orientation.RIGHT_LEFT) ? this.col - Math.floor(itemIndex / this.row) : Math.ceil((itemIndex + 1) / this.row);
						break;
				}
				
				//根据项目所在行列定位坐标
				var itemX:Number = (itemCol - 1) * (item.content.width + this.colSpacing);
				var itemY:Number = (itemRow - 1) * (item.content.height + this.rowSpacing);
				
				if (this.orientation == Orientation.RIGHT_LEFT || this.wrapOrientation == Orientation.RIGHT_LEFT)
				{
					itemX += this.maskLayer.width - this.col * (item.content.width + this.colSpacing) - this.colSpacing;
				}
				
				if (this.orientation == Orientation.BOTTOM_TOP || this.wrapOrientation == Orientation.BOTTOM_TOP)
				{
					itemY += this.maskLayer.height - this.row * (item.content.height + this.rowSpacing) - this.rowSpacing;
				}
				
				item.index = itemIndex;
				item.row = itemRow;
				item.col = itemCol;
				item.content.x = itemX;
				item.content.y = itemY;
				item.content.visible = (this.data == null) ? false : itemIndex < this.data.length;
				
				if (item.content.visible)
				{
					item.data = this.data.element(itemIndex);
					item.selected = (this.selected == item.data || ((this.selected is ArrayList) && (this.selected as ArrayList).contains(item.data)));
				}
			}
			
			this.itemStartIndex = startIndex;
		}
		
		/**
		 * 定位遮罩
		 */
		private function positionMask():void
		{
			this.maskLayer.x = this.paddingLeft + this._maskMargin.left;
			this.maskLayer.y = this.paddingTop + this._maskMargin.top;
		}
		
		/**
		 * 计算遮罩尺寸
		 */
		private function resizeMask():void
		{
			this.maskLayer.width = Math.max(0, (this.vScrollBar.visible) ? this.width - this.paddingLeft - this.paddingRight - this._maskMargin.left - this._maskMargin.right - this.vScrollBar.width : this.width - this.paddingLeft - this.paddingRight - this._maskMargin.left - this._maskMargin.right);
			this.maskLayer.height = Math.max(0, (this.hScrollBar.visible) ? this.height - this.paddingTop - this.paddingBottom - this._maskMargin.top - this._maskMargin.bottom - this.hScrollBar.height : this.height - this.paddingTop - this.paddingBottom - this._maskMargin.top - this._maskMargin.bottom);
		}
		
		/**
		 * 定位容器
		 */
		private function positionContainer():void
		{
			var range:Margin = this.dragRange();
			
			this.container.x = (this.contentAlignH == Align.LEFT) ? range.right : (this.contentAlignH == Align.RIGHT) ? range.left : this.maskMarginLeft + (this.maskLayer.width - this.container.width) / 2;
			this.container.y = (this.contentAlignV == Align.TOP) ? range.bottom : (this.contentAlignV == Align.BOTTOM) ? range.top : this.maskMarginTop + (this.maskLayer.height - this.container.height) / 2;
			//设定内容位置
			this.container.x = (this.hScrollBar.unitDragMode) ? Math.round(this.container.x / this.hScrollBar.unit) * this.hScrollBar.unit : this.container.x;
			this.container.y = (this.vScrollBar.unitDragMode) ? Math.round(this.container.y / this.vScrollBar.unit) * this.vScrollBar.unit : this.container.y;
			
			this.initScrollBar();
		}
		
		/**
		 * 计算容器尺寸
		 */
		private function resizeContainer():void
		{
			this.container.width = (this.itemWidth == 0) ? this.maskLayer.width : this.col * (this.itemWidth + this.colSpacing) - this.colSpacing;
			this.container.height = (this.itemHeight == 0) ? this.maskLayer.height : this.row * (this.itemHeight + this.rowSpacing) - this.rowSpacing;
		}
		
		/**
		 * 初始化滚动条
		 */
		private function initScrollBar():void
		{
			//设定滚动条数值
			var range:Margin = this.dragRange();
			this.hScrollBar.setValue(0, Math.max(0, this.container.width - this.maskLayer.width), isNaN(this.scrollSize) ? this.itemWidth + this.colSpacing : this.scrollSize, this.maskLayer.width);
			this.vScrollBar.setValue(0, Math.max(0, this.container.height - this.maskLayer.height), isNaN(this.scrollSize) ? this.itemHeight + this.rowSpacing : this.scrollSize, this.maskLayer.height);
			
			this.hScrollBar.width = (this.vScrollBar.visible) ? this.width - this.paddingLeft - this.paddingRight - this.vScrollBar.width : this.width - this.paddingLeft - this.paddingRight;
			this.vScrollBar.height = (this.hScrollBar.visible) ? this.height - this.paddingTop - this.paddingBottom - this.hScrollBar.height : this.height - this.paddingTop - this.paddingBottom;
			
			this.hScrollBar.current = this.maskMarginLeft - this.container.x;
			this.vScrollBar.current = this.maskMarginTop - this.container.y;
		}
		
		/**
		 * 测量列表内项目
		 */
		private function measure():void
		{
			var showWidth:Number = this.width - this.paddingLeft - this.paddingRight - this._maskMargin.left - this._maskMargin.right;
			var showHeight:Number = this.height - this.paddingTop - this.paddingBottom - this._maskMargin.top - this._maskMargin.bottom;
			var length:int = (this.data == null) ? 0 : this.data.length;
			
			//计算行列数
			switch (this.orientation)
			{
				case Orientation.HORIZONTAL:
				case Orientation.LEFT_RIGHT:
				case Orientation.RIGHT_LEFT:
					
					if (this.wrap)
					{
						if (this.itemWidth == 0)
						{
							if (isNaN(this.itemMaxWidth) || showWidth < (this.itemMaxWidth + this.colSpacing) * Math.ceil(Math.sqrt(length)) - this.colSpacing)
							{
								this._col = Math.max(1, Math.ceil(Math.sqrt(length)));
							}
							else
							{
								this._col = Math.max(1, Math.floor(showWidth + this.colSpacing) / (this.itemMaxWidth + this.colSpacing))
							}
						}
						else
						{
							this._col = Math.max(1, Math.floor(this.maskLayer.width + this.colSpacing) / (this.itemWidth + this.colSpacing))
						}
					}
					else
					{
						this._col = Math.max(1, length);
					}
					
					this._row = Math.max(1, Math.ceil(length / this.col));
					
					break;
				
				case Orientation.VERTICAL:
				case Orientation.TOP_BOTTOM:
				case Orientation.BOTTOM_TOP:
					
					if (this.wrap)
					{
						if (this.itemHeight == 0)
						{
							if (isNaN(this.itemMaxHeight) || showHeight < (this.itemMaxHeight + this.rowSpacing) * Math.ceil(Math.sqrt(length)) - this.rowSpacing)
							{
								this._row = Math.max(1, Math.ceil(Math.sqrt(length)));
							}
							else
							{
								this._row = Math.max(1, Math.floor(showHeight + this.rowSpacing) / (this.itemMaxHeight + this.rowSpacing));
							}
						}
						else
						{
							this._row = Math.max(1, Math.floor(this.maskLayer.height + this.rowSpacing) / (this.itemHeight + this.rowSpacing));
						}
					}
					else
					{
						this._row = Math.max(1, length);
					}
					
					this._col = Math.max(1, Math.ceil(length / this.row));
					
					break;
			}
			
			this.resizeContainer();
		}
		
		/**
		 * 注册事件侦听
		 */
		private function registerEventListeners():void
		{
			if (this.scrollWheel)
			{
				this.container.addEventListener(MouseEvent.ROLL_OVER, onMouseOver, false, 0, true);
			}
			else
			{
				this.container.removeEventListener(MouseEvent.ROLL_OVER, onMouseOver);
			}
			
			if (this.scrollDrag)
			{
				this.container.addEventListener(MouseEvent.MOUSE_DOWN, onContentMouseDown, false, 0, true);
			}
			else
			{
				this.container.removeEventListener(MouseEvent.MOUSE_DOWN, onContentMouseDown);
			}
			
			this.hScrollBar.addEventListener(Event.CHANGE, onScroll, false, 0, true);
			this.vScrollBar.addEventListener(Event.CHANGE, onScroll, false, 0, true);
			
			if (this.stage != null)
			{
				if (this.cancelMode)
				{
					this.stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown, false, 0, true);
				}
				else
				{
					this.stage.removeEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
				}
			}
		}
		
		/**
		 * 移除事件侦听
		 */
		private function removeEventListeners():void
		{
			this.container.removeEventListener(MouseEvent.ROLL_OVER, onMouseOver);
			this.container.removeEventListener(MouseEvent.ROLL_OUT, onMouseOut);
			this.container.removeEventListener(MouseEvent.MOUSE_DOWN, onContentMouseDown);
			this.hScrollBar.removeEventListener(Event.CHANGE, onScroll);
			this.vScrollBar.removeEventListener(Event.CHANGE, onScroll);
			
			if (this.stage != null)
			{
				this.stage.removeEventListener(Event.MOUSE_LEAVE, onMouseOut);
				this.stage.removeEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
				this.stage.removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
			}
		}
		
		/**
		 * 鼠标移入时
		 * @param event
		 */
		private function onMouseOver(event:MouseEvent):void
		{
			this.container.addEventListener(MouseEvent.ROLL_OUT, onMouseOut, false, 0, true);
			this.stage.addEventListener(Event.MOUSE_LEAVE, onMouseOut, false, 0, true);
			
			if (ExternalInterface.available && this.stage.displayState != StageDisplayState.FULL_SCREEN && this.stage.displayState != StageDisplayState.FULL_SCREEN_INTERACTIVE)
			{
				FlashPlayer.RegisterMouseWheelHandler(this.onMouseWheel);
			}
			else
			{
				this.stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel, false, 0, true);
			}
		}
		
		/**
		 * 鼠标移出时
		 * @param event
		 */
		private function onMouseOut(event:MouseEvent):void
		{
			this.container.removeEventListener(MouseEvent.ROLL_OUT, onMouseOut);
			
			if (this.stage != null)
			{
				this.stage.removeEventListener(Event.MOUSE_LEAVE, onMouseOut);
			}
			
			FlashPlayer.RemoveMouseWheelHandler(this.onMouseWheel);
			this.stage.removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
		}
		
		/**
		 * 滚动条变更时
		 * @param event
		 */
		private function onScroll(event:Event):void
		{
			//获取内容目标坐标
			var x:Number = (this.container.width < this.maskLayer.width) ? this.container.x : this.maskMarginLeft - this.hScrollBar.current;
			var y:Number = (this.container.height < this.maskLayer.height) ? this.container.y : this.maskMarginTop - this.vScrollBar.current;
			
			//如果与当前位置一致则返回
			if (this.container.x == x && this.container.y == y)
			{
				return;
			}
			
			//移除所有缓动效果
			TweenMax.killAll();
			
			if (this.scrollEasing)
			{
				//缓动定位
				var h:Number = Math.abs(this.container.x - x) / this.hScrollBar.amount;
				var v:Number = Math.abs(this.container.y - y) / this.vScrollBar.amount;
				var time:Number = Math.max(isNaN(h) ? 0 : h, isNaN(v) ? 0 : v);
				TweenMax.to(this.container, Math.min(this.maxEaseTime, Math.max(this.minEaseTime, time)), {x: x, y: y, ease: Strong.easeOut, onUpdate: positionItems});
			}
			else
			{
				//直接定位
				this.container.x = x;
				this.container.y = y;
				
				this.positionItems();
			}
		}
		
		/**
		 * 鼠标滚动时
		 * @param delta 滚动行数
		 */
		private function onMouseWheel(data:Object):void
		{
			var delta:int = (data is MouseEvent) ? (data as MouseEvent).delta : data as int;
			
			this.vScrollBar.setCurrent(Math.max(0, this.vScrollBar.current + this.vScrollBar.amount * -1 * delta / 3));
		}
		
		/**
		 * 鼠标按下内容时
		 * @param event
		 */
		private function onContentMouseDown(event:MouseEvent):void
		{
			this.stage.addEventListener(MouseEvent.MOUSE_MOVE, onDragMouseMove, false, 0, true);
			this.stage.addEventListener(MouseEvent.MOUSE_UP, onContentMouseUp, false, 0, true);
			
			//移除所有缓动效果
			TweenMax.killAll();
			
			//设定检测鼠标定位间隔
			clearInterval(this.containerMouseInterval);
			this.containerMouseInterval = setInterval(checkMouse, this.dragRate);
			this.checkMouse();
			
			//设定鼠标按下坐标
			this.containerLocalX = this.container.mouseX * this.container.scaleX;
			this.containerLocalY = this.container.mouseY * this.container.scaleY;
		}
		
		/**
		 * 检测鼠标位置
		 */
		private function checkMouse():void
		{
			this.containerStartX = this.stage.mouseX;
			this.containerStartY = this.stage.mouseY;
			this.containerMouseTime = getTimer();
		}
		
		/**
		 * 鼠标抬起内容时
		 * @param event
		 */
		private function onContentMouseUp(event:Event):void
		{
			if (this.stage != null)
			{
				this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onDragMouseMove);
				this.stage.removeEventListener(MouseEvent.MOUSE_UP, onContentMouseUp);
				this.stage.removeEventListener(Event.MOUSE_LEAVE, onContentMouseUp);
			}
			
			this.container.mouseChildren = true;
			
			var range:Margin = this.dragRange();
			
			//根据鼠标移动方向进行缓动X坐标定位
			var x:Number = (this.scrollEasing) ? this.container.x + this.dragEase * (this.stage.mouseX - this.containerStartX) / (getTimer() - this.containerMouseTime) : this.container.x;
			x = (this.container.x != x && this.container.x < range.right && this.container.x > range.left) ? x : Math.max(range.left, Math.min(range.right, x));
			
			//根据鼠标移动方向进行缓动Y坐标定位
			var y:Number = (this.scrollEasing) ? this.container.y + this.dragEase * (this.stage.mouseY - this.containerStartY) / (getTimer() - this.containerMouseTime) : this.container.y;
			y = (this.container.y != y && this.container.y < range.bottom && this.container.y > range.top) ? y : Math.max(range.top, Math.min(range.bottom, y));
			
			//清除检测鼠标定位间隔
			clearInterval(this.containerMouseInterval);
			
			//更新内容位置
			this.moveTo(this.maskMarginLeft - x, this.maskMarginTop - y);
			
			if (event is MouseEvent)
			{
				(event as MouseEvent).updateAfterEvent();
			}
		}
		
		/**
		 * 鼠标移动内容时
		 * @param event
		 */
		private function onDragMouseMove(event:MouseEvent=null):void
		{
			this.container.mouseChildren = false;
			
			var x:Number =  this.mouseX - this.containerLocalX - this.paddingLeft;
			var y:Number = this.mouseY - this.containerLocalY - this.paddingTop;
			
			this.dragTo(this.maskMarginLeft - x, this.maskMarginTop - y);
			
			if (event != null)
			{
				event.updateAfterEvent();
			}
		}
		
		/**
		 * 数据变更时
		 */
		private function onDataChange(event:Event=null):void
		{
			this.measure();
			
			var showWidth:Number = this.width - this.paddingLeft - this.paddingRight - this._maskMargin.left - this._maskMargin.right;
			var showHeight:Number = this.height - this.paddingTop - this.paddingBottom - this._maskMargin.top - this._maskMargin.bottom;
			
			this.hScrollBar.visible = (this.height - this.paddingTop - this.paddingBottom >= this.hScrollBar.height && this.container.width > showWidth);
			this.vScrollBar.visible = (this.width - this.paddingLeft - this.paddingRight >= this.vScrollBar.width && this.container.height > showHeight);
			
			this.hScrollBar.visible = (this.vScrollBar.visible) ? this.container.width > showWidth - this.vScrollBar.width : this.hScrollBar.visible;
			this.vScrollBar.visible = (this.hScrollBar.visible) ? this.container.height > showHeight - this.hScrollBar.height : this.vScrollBar.visible;
			
			this.initItems();
			this.resizeMask();
			this.resizeContainer();
			this.positionItems();
			
			this.hScrollBar.setValue(0, Math.max(0, this.container.width - this.maskLayer.width), isNaN(this.scrollSize) ? this.itemWidth + this.colSpacing : this.scrollSize, this.maskLayer.width);
			this.vScrollBar.setValue(0, Math.max(0, this.container.height - this.maskLayer.height), isNaN(this.scrollSize) ? this.itemHeight + this.rowSpacing : this.scrollSize, this.maskLayer.height);
			
			var maxH:Number = Math.max(0, this.container.width - this.maskLayer.width);
			
			if (this.hScrollBar.current > maxH)
			{
				this.hScrollBar.setCurrent(maxH);
			}
			
			if (this.hScrollBar.current < 0 && this.hScrollBar.current != this.maskMarginLeft - this.container.x)
			{
				this.hScrollBar.setCurrent(this.maskMarginLeft - this.container.x);
			}
			
			var maxV:Number = Math.max(0, this.container.height - this.maskLayer.height);
			
			if (this.vScrollBar.current > maxV)
			{
				this.vScrollBar.setCurrent(maxV);
			}
			
			if (this.vScrollBar.current < 0 && this.vScrollBar.current != this.maskMarginTop - this.container.y)
			{
				this.vScrollBar.setCurrent(this.maskMarginTop - this.container.y);
			}
		}
		
		/**
		 * 舞台鼠标按下时
		 * @param event
		 */
		private function onStageMouseDown(event:MouseEvent):void
		{
			var array:Array = this.stage.getObjectsUnderPoint(new Point(this.stage.mouseX, this.stage.mouseY));
			
			if (array.indexOf(this) < 0)
			{
				this.selected = null;
			}
		}
		
		/**
		 * 鼠标点击时
		 * @param event
		 */
		private function onClick(event:MouseEvent):void
		{
			var clickData:* = (event.currentTarget as IDataItem).data;
			
			if (this.multiSelected && event.ctrlKey)
			{
				//按住Ctrl多选
				if (this.selected is ArrayList)
				{
					//当前选择是列表
					if (!(this.selected as ArrayList).contains(clickData))
					{
						//所选数据不在已选列表中
						this.selected = (this.selected as ArrayList).concat(new Array(clickData));
					}
					else
					{
						//可取消模式，或不是唯一数据
						if (this.cancelMode || (this.selected as ArrayList).length > 1)
						{
							(this.selected as ArrayList).remove(clickData);
							this.selected = this.selected;
						}
					}
				}
				else
				{
					//当前选择不是列表
					this.selected = (this.selected == null) ? new ArrayList(clickData) : (this.selected is ArrayList) ? (this.selected as ArrayList).concat(new Array(clickData)) : new ArrayList(this.selected, clickData);
				}
			}
			else
			{
				//直接点击单选
				if (this.cancelMode && this.selected == clickData)
				{
					//可取消模式，并且点击当前选择
					this.selected = null;
					return;
				}
				
				this.selected = clickData;
			}
		}
	
	}
}

import com.siao.component.IDataItem;
import com.siao.component.IListItem;
import com.siao.component.ISelectItem;
import com.siao.data.ValueObject;
import com.siao.events.DataChangeEvent;

import flash.display.DisplayObject;

/**
 * 滚动列表项目
 * @author SiaoLeon
 */
class ScrollListItem implements IDataItem, ISelectItem, IListItem
{
	private var _content:DisplayObject;
	
	/**
	 * 当前项目的显示内容对象
	 * @return
	 */
	public function get content():DisplayObject
	{
		return this._content;
	}
	
	private var _row:uint;
	
	/**
	 * 当前项目所在行
	 * @return
	 */
	public function get row():uint
	{
		return this._row;
	}
	
	public function set row(value:uint):void
	{
		this._row = value;
	}
	
	private var _col:uint;
	
	/**
	 * 当前项目所在列
	 * @return
	 */
	public function get col():uint
	{
		return this._col;
	}
	
	public function set col(value:uint):void
	{
		this._col = value;
	}
	
	private var _data:*;
	
	public function get data():*
	{
		return this._data;
	}
	
	public function set data(value:*):void
	{
		this._data = value;
		
		if (value is ValueObject)
		{
			(value as ValueObject).addEventListener(DataChangeEvent.CHANGE, onDataChange, false, 0, true);
		}
		
		this.onDataChange();
	}
	
	private var _index:int = -1;
	
	/**
	 * 当前项目所在索引位置
	 * @return
	 */
	public function get index():int
	{
		return this._index;
	}
	
	public function set index(value:int):void
	{
		this._index = value;
		
		if (this.content is IListItem)
		{
			(this.content as IListItem).index = value;
		}
	}
	
	private var _selected:Boolean;
	
	public function get selected():Boolean
	{
		return this._selected;
	}
	
	public function set selected(value:Boolean):void
	{
		this._selected = value;
		
		if (this.content is ISelectItem)
		{
			(this.content as ISelectItem).selected = value;
		}
	}
	
	/**
	 * 构造函数
	 * @param itemClass 项目显示内容的类
	 */
	function ScrollListItem(itemClass:Class)
	{
		this._content = new itemClass();
	}
	
	private function onDataChange(event:DataChangeEvent=null):void
	{
		(this.content as IDataItem).data = this.data;
	}

}
